package ua.com.learnjava.controller;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.util.ArrayList;

import ua.com.learnjava.common.RegistrationUser;
import ua.com.learnjava.common.Course;
import ua.com.learnjava.common.Chapter;

@ControllerAdvice
@Controller
public class DefaultController {
	private final AtomicLong counter = new AtomicLong();
	
	private static final String MAIN_P_RIGHT_LOGO = 
			"Твоя первая JAVA программа за 5 минут!";
	
	private static final String MAIN_P_LEARN_JAVA_COLUMN = 
			"Не умеете программировать, но очень хотите научиться? " +
			"На нашем сайте у вас есть удивительная возможность " +
			"написать свое первое приложение за 5 минут! Вы " +
			"сможете посетить незабываемые занятия.";
	
	private static final String MAIN_P_DOWNLOAD_COLUMN = 
			"В нашем архиве вы найдете все необходимое для " +
			"программирования с нуля, библиотеки, плагины, IDE, и " +
			"многое другое.";

	
    protected AuthenticationManager authenticationManager;
    protected InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> configurer;
    
	@RequestMapping("")
	public String loadHomePage(Model m) {
		//Need to be logged via Log4j
		System.out.println("######## calling home page /");
		counter.incrementAndGet();
		
		
		List<String> news = generateNews();
		
		
		m.addAttribute("currentDate", getCurrentDate());
		m.addAttribute("siteUpdateCount", counter);
		m.addAttribute("rightLogo", MAIN_P_RIGHT_LOGO);
		m.addAttribute("learnJavaColumn", MAIN_P_LEARN_JAVA_COLUMN);
		m.addAttribute("downloadJavaColumn", MAIN_P_DOWNLOAD_COLUMN);
		m.addAttribute("newsColumn", news);
		
		List<String> menu = generateMenu(0);
		m.addAttribute("menu", menu);

		return "index";
	}
	
	@RequestMapping("login")
	public String loadLoginPage(Model m) {
		//Need to be logged via Log4j
		System.out.println("######## calling login page");
		List<String> menu = generateMenu(4);
		m.addAttribute("menu", menu);
		return "login";
	}
	
	
	@RequestMapping(value = "signup", method = RequestMethod.POST)
    public String createNewUser(@ModelAttribute("user") RegistrationUser user, 
    		BindingResult result,
			HttpServletRequest request){
		System.out.println("#####################################");
		System.out.println("######## calling signup page ########");
		System.out.println("#####################################");
	
		if (result.hasErrors()) {
			System.out.println(result.getAllErrors());
			return "registration";
		} 
		System.out.println("user details:" + user);
		authenticateUserAndSetSession(user, request);
		
        return "redirect:index";
    }

	private void authenticateUserAndSetSession(RegistrationUser user, HttpServletRequest request){
		System.out.println("adding a user:" + user);
		Set<GrantedAuthority> authoritites = new HashSet<GrantedAuthority>();
		authoritites.add(new SimpleGrantedAuthority("USER"));
		UserDetails newUser = new User(user.getUsername(),user.getPassword(), authoritites);
		configurer.getUserDetailsService().createUser(newUser);
        //.withUser(user.getUsername()).password(user.getPassword()).roles("USER");
		System.out.println("user added:" + newUser);
		UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
		user.getUsername(), user.getPassword());
		// generate session if one doesn't exist
		request.getSession();

		token.setDetails(new WebAuthenticationDetails(request));
		Authentication authenticatedUser = authenticationManager.authenticate(token);

		SecurityContextHolder.getContext().setAuthentication(authenticatedUser);
	}
	
	@RequestMapping("registration")
	public String loadRegistrationPage(Model m) {
		//Need to be logged via Log4j
		System.out.println("######## calling registration page");
		List<String> menu = generateMenu(4);
		m.addAttribute("menu", menu);
		return "registration";
	}
	
    @Autowired
    public void registerGlobalAuthentication(
            AuthenticationManagerBuilder auth) throws Exception {
		System.out.println("######## calling registerGlobalAuthentication page");
    	this.authenticationManager = auth.getOrBuild();
        this.configurer = auth.getConfigurer(InMemoryUserDetailsManagerConfigurer.class);
		configurer
                .withUser("admin").password("admin").roles("USER");

    }
//	@RequestMapping(value = "/newUser", method = RequestMethod.POST)
//	public String createNewUser(final @Valid @ModelAttribute Person user,
//	                                  final BindingResult result,
//	                                  final SessionStatus status,
//	                                  final @RequestParam(value = "unencodedPassword", required = true) String password) {
//	        user.getRoles().add(new Role(user, Role.APPLICATION_ROLE.ROLE_USER));
//	        //userDao.createNewUser(user);
//	        return "registration";
//	}
	
	@RequestMapping("index")
	public String loadIndexPage(Model m) {
		return loadHomePage(m);
	}
	
	@RequestMapping("lessons")
	public String loadLessonsPage(Model m) {
		//Need to be logged via Log4j
		System.out.println("######## calling lessons page");
		List<String> menu = generateMenu(1);
		m.addAttribute("menu", menu);
		return "lessons";
	}
	
	@RequestMapping("lesson_ready/{course}")
	public String loadReadyLessonsPage(
			@PathVariable("course")String course, Model m){
		System.out.println("page is " + course);
		System.out.println("######## calling Ready Lessons page");
		//Need to be logged via Log4j
		String courseImageLink = "";
		String courseName = "";
		String linkName = "";
		String description = "";
		String userStatus = "";
		if(course.equals("calculator")){
			System.out.println("loading calculator details");
			courseImageLink =  "<img src=\"/images/calculator_ce.png\" alt=\"calculator\"/>";
			courseName = "Калькулятор";
			description = "Самый крутой калькулятор";	
			userStatus = "Еще не начинал";
			linkName = course;
			//throw new NestedServletException();
		}
		m.addAttribute("linkName", linkName);
		m.addAttribute("courseImageLink", courseImageLink);
		m.addAttribute("courseName", courseName);
		m.addAttribute("description", description);
		m.addAttribute("userStatus", userStatus);
		
		List<String> menu = generateMenu(1);
		m.addAttribute("menu", menu);
		
		return "lesson_ready_main";
	}
	
	private List<String> generateNews(){
		List<String> news = new ArrayList<String>();
		news.add("<p class=\"news_time\">" + getCurrentDate() + "</p><p class=\"news_text\"> Вы " + counter + " кто зашел на сайт.</p>");
		
		news.add("<p class=\"news_time\">9.12.2013</p><p class=\"news_text\"> Изменилась главная страница, удалена кнопка Скачать и в нижней части страницы теперь не три а две колонки: О проекте и Новости.</p>");
		news.add("<p class=\"news_time\">8.12.2013</p><p class=\"news_text\"> Добавлена обработка и отображение ошибок. <a href=\"/generateTestException\">пример</a></p>");
		news.add("<p class=\"news_time\">7.12.2013</p><p class=\"news_text\"> Добавлена обработка неправильных запросов.</p>");
		news.add("<p class=\"news_time\">30.11.2013</p><p class=\"news_text\"> Добавлена регистрация в памяти.</p>");
		news.add("<p class=\"news_time\">15.11.2013</p><p class=\"news_text\"> Добавлена авторизация.</p>");
		news.add("<p class=\"news_time\">11.11.2013</p><p class=\"news_text\"> Добавлена странца с выбором уроков.</p>");
		news.add("<p class=\"news_time\">10.11.2013</p><p class=\"news_text\"> Вкомичены 3 версии веб темплейтов.</p>");
		news.add("<p class=\"news_time\">1.11.2013</p><p class=\"news_text\"> Запустили бета версию сайта.</p>");
		return news;
	}
	
	public static List<String> generateMenu(int currentMenuItem){
		String c[] = new String[5];
		String current = "class=\"current\"";
		c[currentMenuItem] = current;
		List<String> menu = new ArrayList<String>();
		menu.add("<a href=\"/index\" "+ c[0] + " >Главная</a>");
		menu.add("<a href=\"/lessons\" "+ c[1] + " >Учить Джаву</a>");
		menu.add("<a href=\"/download\" "+ c[2] + " >Скачать</a>");
		menu.add("<a href=\"/contacts\" "+ c[3] + " >Контакты</a>");
		return menu;
	}
	
	private String getCurrentDate(){
		Calendar c = Calendar.getInstance(); 
		String currentDate = c.get(c.DAY_OF_MONTH) + "." + (c.get(c.MONTH) + 1) + "." + c.get(c.YEAR);
		return currentDate;
	}
	
	
	private ArrayList<Course> getCourses() {
        ArrayList<Course> courses = new ArrayList<Course>();

        Course course = new Course();
        course.setName("Calculator");
        course.setDate("05-11-2013");

        ArrayList<Chapter> chapters = new ArrayList<Chapter>();
        Chapter chapter = new Chapter();
        chapter.setName("Input/Output");
        chapter.setText("This is first chapter");
        chapters.add(chapter);

        course.setChapters(chapters);

        courses.add(course);

        return courses;
    }

	
	
	@RequestMapping("lesson_ready_detail/{course}/{lesson}")
	public String loadReadyLessonsPage(
			@PathVariable("course")String course, 
			@PathVariable("lesson")String lesson, Model m){
		System.out.println("page is " + course);
		System.out.println("######## calling Ready Lessons page");
		//Need to be logged via Log4j
		String courseImageLink = "";
		String lessonName = "";
		String linkName = "";
		String description = "";
		String userStatus = "";
		if(course.equals("calculator")){
			System.out.println("loading calculator details");
			courseImageLink =  "<img src=\"/images/calculator_ce.png\" alt=\"calculator\"/>";
			linkName = course;
			//throw new NestedServletException();
			if(lesson.equals("lesson_1")){
				lessonName = "Урок 1 - Начало (вывод текста)";
				description = "1.1 установи джаву, 1.2 создай папку, файлы, мэин класс с выводом текста(продемонстрировать какую-то текстографику) 1.3 научись компилить, 1.4 запускать пустое приложение (1.5) тест какой-то, типа попробуй вывести какой-то другой текст";	
			}
			else{
				linkName = "";		
			}
		}
		m.addAttribute("linkName", linkName);
		m.addAttribute("courseImageLink", courseImageLink);
		m.addAttribute("lessonName", lessonName);
		m.addAttribute("description", description);
		m.addAttribute("userStatus", userStatus);
		
		List<String> menu = generateMenu(1);
		m.addAttribute("menu", menu);
		
		return "lesson_ready_main";
	}
}
